home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Harvest C 1.3 / Source Code / CHarvestDoc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-20  |  48.1 KB  |  1,834 lines  |  [TEXT/ALFA]

  1. /*
  2.     Harvest C
  3.     Copyright 1992 Eric W. Sink.  All rights reserved.
  4.     
  5.     This file is part of Harvest C.
  6.     
  7.     Harvest C is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU Generic Public License as published by
  9.     the Free Software Foundation; either version 2, or (at your option)
  10.     any later version.
  11.     
  12.     Harvest C is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.     
  17.     You should have received a copy of the GNU General Public License
  18.     along with Harvest C; see the file COPYING.  If not, write to
  19.     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.     
  21.     Harvest C is not in any way a product of the Free Software Foundation.
  22.     Harvest C is not GNU software.
  23.     Harvest C is not public domain.
  24.  
  25.     This file may have other copyrights which are applicable as well.
  26.  
  27. */
  28.  
  29. /****
  30.  * CHarvestDoc.c
  31.  *
  32.  *    Document methods for Harvest C
  33.  *
  34.  *  Copyright © 1990 Symantec Corporation.  All rights reserved.
  35.  *
  36.  ****/
  37.  
  38. #include "Global.h"
  39. #include "Constants.h"
  40. #include "Commands.h"
  41. #include "CApplication.h"
  42. #include "CBartender.h"
  43. #include "CDataFile.h"
  44. #include "CDecorator.h"
  45. #include "CDesktop.h"
  46. #include "CError.h"
  47. #include "CPanorama.h"
  48. #include "CScrollPane.h"
  49. #include "CHarvestApp.h"
  50. #include "CHarvestDoc.h"
  51. #include "CHarvestOptions.h"
  52. #include "CHarvestPane.h"
  53. #include "COptionsDialog.h"
  54. #include "CProjectInfoDialog.h"
  55. #include "CCheckBox.h"
  56. #include "CRadioControl.h"
  57. #include "CRadioGroupPane.h"
  58. #include "CWarningsDialog.h"
  59. #include "CWarningsArray.h"
  60. #include "CDialogText.h"
  61. #include "CIntegerText.h"
  62. #include "TBUtilities.h"
  63. #include "CWindow.h"
  64. #include "CFile.h"
  65. #include "CList.h"
  66. #include "CResourceFile.h"
  67. #include "CSourceFile.h"
  68. #include "CLibraryFile.h"
  69. #include <Packages.h>
  70. #include "AppleEvents.h"
  71. #include "Aliases.h"
  72. #include "HarvestCommands.h"
  73. #include "CErrorLog.h"
  74. #include "structs.h"
  75. #include "linkstruct.h"
  76.  
  77. #define    WINDHarvest        500        /* Resource ID for WIND template */
  78.  
  79. extern    CHarvestApp *gApplication;    /* The application */
  80. extern    tSystem        gSystem;
  81. extern    CHarvestDoc    *gProject;
  82. extern    CErrorLog    *gErrs;
  83. extern    CSourceFile *gCurSourceFile;
  84. extern    CBartender    *gBartender;    /* The menu handling object */
  85. extern    CDecorator    *gDecorator;    /* Window dressing object    */
  86. extern    CDesktop    *gDesktop;        /* The enclosure for all windows */
  87. extern    CBureaucrat    *gGopher;        /* The current boss in the chain of command */
  88. extern    OSType        gSignature;        /* The application's signature */
  89. extern    CError        *gError;        /* The global error handler */
  90. extern    int                             LinkErrorCount;
  91. extern    SegmentVia_t                    SegmentList;
  92. extern    DATAZone_t                      theDATA;
  93. extern    CursHandle            gWatchCursor;        /* Watch cursor for waiting            */
  94.  
  95. enum {
  96.     kTrigraphsItem = 4,
  97.     kBigGlobalsItem,
  98.     k68020Item,
  99.     k68881Item,
  100.     kSignedCharItem,
  101.     kMacsBugitem
  102. };
  103.  
  104. enum {
  105.     kSigFieldItem = 3,
  106.     kPartitionItem,
  107.     kSizeFlagsItem
  108. };
  109.  
  110. Boolean FindAProcess(OSType signature,ProcessSerialNumber *process,
  111.                         ProcessInfoRec *InfoRec,
  112.                         FSSpecPtr aFSSpecPtr)
  113. {
  114.     process->highLongOfPSN = 0;
  115.     process->lowLongOfPSN = kNoProcess;
  116.     
  117.     InfoRec->processInfoLength = sizeof(ProcessInfoRec);
  118.     InfoRec->processName = (StringPtr) NewPtr(32);
  119.     InfoRec->processAppSpec = aFSSpecPtr;
  120.     
  121.     while (GetNextProcess(process) == noErr) {
  122.         if (GetProcessInformation(process,InfoRec) == noErr) {
  123.             if ((InfoRec->processType == 'APPL') &&
  124.                 (InfoRec->processSignature == signature)) {
  125.                 return TRUE;
  126.             }
  127.         }
  128.     }
  129.     return FALSE;
  130. }
  131.  
  132.  
  133.  
  134. /***
  135.  * IHarvestDoc
  136.  *
  137.  *    This is your document's initialization method.
  138.  *    If your document has its own instance variables, initialize
  139.  *    them here.
  140.  *
  141.  *    The least you need to do is invoke the default method.
  142.  *
  143.  ***/
  144.  
  145. void CHarvestDoc::IHarvestDoc(CApplication *aSupervisor, Boolean printable)
  146.  
  147. {
  148.     CDocument::IDocument(aSupervisor, printable);
  149.  
  150.     itsSourceFiles = new(CList);
  151.     itsSourceFiles->IList();
  152.     itsOptions = new CHarvestOptions;
  153.     itsOptions->IHarvestOptions();
  154.     itsWarnings = new CWarningsArray;
  155.     itsWarnings->IWarningsArray(itsOptions);
  156.     itsWarnings->AddWarning("\pEmpty expression stmt",WARN_emptystatement,TRUE);
  157.     itsWarnings->AddWarning("\pMulti-character constant",WARN_multicharconstant,FALSE);
  158.     itsWarnings->AddWarning("\pRedundant cast",WARN_redundantcast,FALSE);
  159.     itsWarnings->AddWarning("\pEquivalence test of floating type",WARN_floateqcompare,TRUE);
  160.     itsWarnings->AddWarning("\pDiscarded function result",WARN_discardfuncresult,FALSE);
  161.     itsWarnings->AddWarning("\pAssignment as if conditional",WARN_assignif,TRUE);
  162.     itsWarnings->AddWarning("\pNon-void function has no return statement",WARN_nonvoidreturn,TRUE);
  163.     itsWarnings->AddWarning("\pConstant expression as if condition",WARN_constantif,TRUE);
  164.     itsWarnings->AddWarning("\pComparison of pointer and integer",WARN_comparepointerint,TRUE);
  165.     itsWarnings->AddWarning("\pAssignment of nonequivalent type to a pointer",WARN_pointernonequivassign,TRUE);
  166.     itsWarnings->AddWarning("\pReturn of nonequivalent type to a pointer",WARN_pointernonequivreturn,TRUE);
  167.     itsWarnings->AddWarning("\pPass of nonequivalent type to a pointer",WARN_pointernonequivarg,TRUE);
  168.     itsWarnings->AddWarning("\pConstant expression as switch condition",WARN_constantswitch,TRUE);
  169.     itsWarnings->AddWarning("\pConstant expression as while loop condition",WARN_constantwhile,TRUE);
  170.     itsWarnings->AddWarning("\pConstant expression as do-while loop condition",WARN_constantdowhile,TRUE);
  171.     itsWarnings->AddWarning("\pConstant expression as for loop condition",WARN_constantfor,TRUE);
  172.     itsWarnings->AddWarning("\pSwitch expression not of integral type",WARN_nonintegralswitch,TRUE);
  173.     itsWarnings->AddWarning("\pVolatile is not handled by this compiler",WARN_novolatile,TRUE);
  174.     itsWarnings->AddWarning("\pUnused variable: ",WARN_unusedvariable,TRUE);
  175.     itsWarnings->AddWarning("\pDead code",WARN_deadcode,TRUE);
  176.     itsWarnings->AddWarning("\pImplicit decl : ",WARN_implicitdecl,FALSE);
  177.     itsWarnings->AddWarning("\pRe#definition : ",WARN_preprocredef,FALSE);
  178.     itsWarnings->AddWarning("\pPossible nested comment",WARN_nestedcomment,TRUE);
  179.     itsWarnings->AddWarning("\pgoto statement found",WARN_goto,TRUE);
  180.     itsWarnings->AddWarning("\pMultiple function returns",WARN_multireturn,TRUE);
  181.     itsWarnings->AddWarning("\pEmpty compound statement",WARN_emptycompound,TRUE);
  182.     itsWarnings->AddWarning("\pMissing function return type - default to int",WARN_missingreturntype,TRUE);
  183.     itsWarnings->AddWarning("\pTrigraph found",WARN_trigraphs,TRUE);
  184.     itsWarnings->AddWarning("\ppascal keyword found",WARN_pascal,FALSE);
  185.     itsWarnings->AddWarning("\pSemicolon after function body",WARN_semiafterfunction,TRUE);
  186.  
  187.     itsPrefix = NULL;
  188.     StdAppVol = -1;
  189.     StdAppDir = -1;
  190.     CopyPString("\papp.out",StdAppName);
  191.     itsPartition = 384*1024;
  192.     itsSignature = '????';
  193.     itsSizeFlags = 0;
  194.     gProject = this;
  195. }
  196.  
  197. /***
  198.  * AddLibraryFileHFS
  199.  *
  200.  *
  201.  ***/
  202.  
  203. void CHarvestDoc::AddLibraryFileHFS(Str63 aName,short aVolNum,long aDirID)
  204.  
  205. {
  206.     CDataFile *newFile;
  207.     CLibraryFile *newLibraryFile;
  208.     newFile = new(CDataFile);
  209.     newFile->IDataFile();
  210.     newFile->SpecifyHFS(aName,aVolNum,aDirID);
  211.     newLibraryFile = new(CLibraryFile);
  212.     newLibraryFile->ILibraryFile(newFile);
  213.     itsSourceFiles->Append((CObject *) newLibraryFile);
  214.     itsTable->AddRow(1,-1);
  215. }
  216.  
  217. /***
  218.  * AddSourceFileHFS
  219.  *
  220.  *
  221.  ***/
  222.  
  223. void CHarvestDoc::AddSourceFileHFS(Str63 aName,short aVolNum,long aDirID)
  224.  
  225. {
  226.     CDataFile *newFile;
  227.     CSourceFile *newSourceFile;
  228.     newFile = new(CDataFile);
  229.     newFile->IDataFile();
  230.     newFile->SpecifyHFS(aName,aVolNum,aDirID);
  231.     newSourceFile = new(CSourceFile);
  232.     newSourceFile->ISourceFile(newFile);
  233.     itsSourceFiles->Append((CObject *) newSourceFile);
  234.     itsTable->AddRow(1,-1);
  235. }
  236.  
  237. /***
  238.  * AddSourceFile
  239.  *
  240.  *
  241.  ***/
  242.  
  243. void CHarvestDoc::AddSourceFile(SFReply *theFile)
  244.  
  245. {
  246.     CDataFile *newFile;
  247.     FInfo fileInfo;
  248.     CSourceFile *newSourceFile;
  249.     CLibraryFile *newLibFile;
  250.     CResourceFile *newResourceFile;
  251.     newFile = new(CDataFile);
  252.     newFile->IDataFile();
  253.     newFile->SFSpecify(theFile);
  254.     /* Here, we check the format of the name and the file type, and add the
  255.        appropriate object, library/source/resource to the project */
  256.     newFile->GetMacFileInfo(&fileInfo);
  257.     if (fileInfo.fdType == 'TEXT') {
  258.         newSourceFile = new(CSourceFile);
  259.         newSourceFile->ISourceFile(newFile);
  260.         itsSourceFiles->Append((CObject *) newSourceFile);
  261.         itsTable->AddRow(1,-1);
  262.     }
  263.     else if (fileInfo.fdType == 'OBJ ') {
  264.         newLibFile = new(CLibraryFile);
  265.         newLibFile->ILibraryFile(newFile);
  266.         itsSourceFiles->Append((CObject *) newLibFile);
  267.         itsTable->AddRow(1,-1);
  268.     }
  269.     else if (fileInfo.fdCreator == 'RSED') {
  270.         newResourceFile = new(CResourceFile);
  271.         newResourceFile->IResourceFile(newFile);
  272.         itsSourceFiles->Append((CObject *) newResourceFile);
  273.         itsTable->AddRow(1,-1);
  274.     }
  275.     else if (fileInfo.fdType == 'rsrc') {
  276.         newResourceFile = new(CResourceFile);
  277.         newResourceFile->IResourceFile(newFile);
  278.         itsSourceFiles->Append((CObject *) newResourceFile);
  279.         itsTable->AddRow(1,-1);
  280.     }
  281. }
  282.  
  283. /***
  284.  * AddResourceFileHFS
  285.  *
  286.  *
  287.  ***/
  288.  
  289. void CHarvestDoc::AddResourceFileHFS(Str63 aName,short aVolNum,long aDirID)
  290.  
  291. {
  292.     CDataFile *newFile;
  293.     CResourceFile *newResourceFile;
  294.     newFile = new(CDataFile);
  295.     newFile->IDataFile();
  296.     newFile->SpecifyHFS(aName,aVolNum,aDirID);
  297.     newResourceFile = new(CResourceFile);
  298.     newResourceFile->IResourceFile(newFile);
  299.     itsSourceFiles->Append((CObject *) newResourceFile);
  300.     itsTable->AddRow(1,-1);
  301. }
  302.  
  303. /***
  304.  * AddResourceFile
  305.  *
  306.  *
  307.  ***/
  308.  
  309. void CHarvestDoc::AddResourceFile(SFReply *theFile)
  310.  
  311. {
  312.     CDataFile *newFile;
  313.     CResourceFile *newResourceFile;
  314.     newFile = new(CDataFile);
  315.     newFile->IDataFile();
  316.     newFile->SFSpecify(theFile);
  317.     newResourceFile = new(CResourceFile);
  318.     newResourceFile->IResourceFile(newFile);
  319.     itsSourceFiles->Append((CObject *) newResourceFile);
  320.     itsTable->AddRow(1,-1);
  321. }
  322.  
  323. /***
  324.  * AddLibFile
  325.  *
  326.  *
  327.  ***/
  328.  
  329. void CHarvestDoc::AddLibFile(SFReply *theFile)
  330.  
  331. {
  332.     CDataFile *newFile;
  333.     CLibraryFile *newSourceFile;
  334.     newFile = new(CDataFile);
  335.     newFile->IDataFile();
  336.     newFile->SFSpecify(theFile);
  337.     newSourceFile = new(CLibraryFile);
  338.     newSourceFile->ILibraryFile(newFile);
  339.     itsSourceFiles->Append((CObject *) newSourceFile);
  340.     itsTable->AddRow(1,-1);
  341. }
  342.  
  343. /***
  344.  * Dispose
  345.  *
  346.  *    This is your document's destruction method.
  347.  *    If you allocated memory in your initialization method
  348.  *    or opened temporary files, this is the place to release them.
  349.  *
  350.  *    Be sure to call the default method!
  351.  *
  352.  ***/
  353.  
  354. void CHarvestDoc::Dispose(void)
  355.  
  356. {
  357. #ifdef Undefined    /* caused illegal inst 5 March */
  358.     itsSourceFiles->Dispose();
  359.     itsOptions->Dispose();
  360.     itsWarnings->Dispose();
  361. #endif
  362.     inherited::Dispose();
  363. }
  364.  
  365. void CHarvestDoc::DoOptions(CHarvestOptions *theOpts)
  366. {
  367.     COptionsDialog *dialog;
  368.     long cmd;
  369.     CCheckBox *trigraphsBox;
  370.     CCheckBox *globalsBox;
  371.     CCheckBox *mc68020Box;
  372.     CCheckBox *mc68881Box;
  373.     CCheckBox *signedCharsBox;
  374.     CCheckBox *MacsBugBox;
  375.  
  376.     dialog = new COptionsDialog;
  377.     dialog->IOptionsDialog(500,this);
  378.     
  379.     /* Now initialize states of the boxes */
  380.     trigraphsBox = (CCheckBox *) dialog->itsWindow->FindViewByID( kTrigraphsItem);
  381.     globalsBox = (CCheckBox *) dialog->itsWindow->FindViewByID( kBigGlobalsItem);
  382.     mc68020Box = (CCheckBox *) dialog->itsWindow->FindViewByID( k68020Item);
  383.     mc68881Box = (CCheckBox *) dialog->itsWindow->FindViewByID( k68881Item);
  384.     signedCharsBox = (CCheckBox *) dialog->itsWindow->FindViewByID( kSignedCharItem);
  385.     MacsBugBox = (CCheckBox *) dialog->itsWindow->FindViewByID( kMacsBugitem);
  386.     
  387.     trigraphsBox->SetValue(theOpts->trigraphs ? BUTTON_ON : BUTTON_OFF);
  388.     globalsBox->SetValue(theOpts->bigGlobals ? BUTTON_ON : BUTTON_OFF);
  389.     mc68020Box->SetValue(theOpts->useMC68020 ? BUTTON_ON : BUTTON_OFF);
  390.     mc68881Box->SetValue(theOpts->useMC68881 ? BUTTON_ON : BUTTON_OFF);
  391.     signedCharsBox->SetValue(theOpts->signedChars ? BUTTON_ON : BUTTON_OFF);
  392.     MacsBugBox->SetValue(theOpts->MacsBugSymbols ? BUTTON_ON : BUTTON_OFF);
  393.  
  394.     
  395.     dialog->BeginDialog();
  396.     cmd = dialog->DoModalDialog(cmdOK);
  397.     if (cmd == cmdOK)
  398.     {
  399.         theOpts->trigraphs = trigraphsBox->IsChecked();
  400.         theOpts->bigGlobals = globalsBox->IsChecked();
  401.         theOpts->useMC68020 = mc68020Box->IsChecked();
  402.         theOpts->useMC68881 = mc68881Box->IsChecked();
  403.         theOpts->signedChars = signedCharsBox->IsChecked();
  404.         theOpts->MacsBugSymbols = MacsBugBox->IsChecked();
  405.     }
  406.     ForgetObject(dialog);
  407. }
  408.  
  409. void CHarvestDoc::DoWarnings(CHarvestOptions *theOpts,CWarningsArray *theWarnings)
  410. {
  411.     CWarningsDialog *dialog;
  412.     long cmd;
  413.  
  414.     dialog = new CWarningsDialog;
  415.     dialog->IWarningsDialog(theOpts,theWarnings);
  416.     
  417.     dialog->BeginDialog();
  418.     cmd = dialog->DoModalDialog(cmdOK);
  419.     if (cmd == cmdOK)
  420.     {
  421.     }
  422.     ForgetObject(dialog);
  423. }
  424.  
  425. char *OSTypeToString(OSType val,char *s)
  426. {
  427.     *((long *) s) = val;
  428.     s[4] = 0;
  429.     return s;
  430. }
  431.  
  432. void CHarvestDoc::DoSetProjectInfo(void)
  433. {
  434.     Str255 theSig;
  435.     CProjectInfoDialog *dialog;
  436.     long cmd;
  437.     CDialogText *sigField;
  438.     CIntegerText *partitionField;
  439.     CIntegerText *sizeFlagsField;
  440.     char sigString[8];
  441.  
  442.     dialog = new CProjectInfoDialog;
  443.     dialog->IProjectInfoDialog(501,this);
  444.     
  445.     sigField = (CDialogText *) dialog->itsWindow->FindViewByID( kSigFieldItem);
  446.     partitionField = (CIntegerText *) dialog->itsWindow->FindViewByID( kPartitionItem);
  447.     sizeFlagsField = (CIntegerText *) dialog->itsWindow->FindViewByID( kSizeFlagsItem);
  448.  
  449.     /* Now initialize states of the textfields */
  450.     
  451.     OSTypeToString(itsSignature,sigString);
  452.     c2pstr(sigString);
  453.     sigField->SetTextString((unsigned char *) sigString);
  454.     partitionField->SetIntValue(itsPartition/1024);
  455.     sizeFlagsField->SetIntValue(itsSizeFlags);
  456.  
  457.     dialog->BeginDialog();
  458.     cmd = dialog->DoModalDialog(cmdOK);
  459.     if (cmd == cmdOK)
  460.     {
  461.         sigField->GetTextString(theSig);
  462.         p2cstr(theSig);
  463.         itsSignature = MakeOSType((char *) theSig);
  464.         itsPartition = partitionField->GetIntValue()*1024;
  465.         itsSizeFlags = sizeFlagsField->GetIntValue();
  466.     }
  467.     ForgetObject(dialog);
  468. }
  469.  
  470. /***
  471.  * DoCommand
  472.  *
  473.  *    This is the heart of your document.
  474.  *    In this method, you handle all the commands your document
  475.  *    deals with.
  476.  *
  477.  *    Be sure to call the default method to handle the standard
  478.  *    document commands: cmdClose, cmdSave, cmdSaveAs, cmdRevert,
  479.  *    cmdPageSetup, cmdPrint, and cmdUndo. To change the way these
  480.  *    commands are handled, override the appropriate methods instead
  481.  *    of handling them here.
  482.  *
  483.  ***/
  484.  
  485. void CHarvestDoc::DoCommand(long theCommand)
  486.  
  487. {
  488.     SFReply theFile;
  489.     Cell aCell = {0,0};
  490.     Boolean thereIsASelection = false;
  491.             if (itsTable->GetSelect(false,&aCell)) {
  492.                 thereIsASelection = true;
  493.             }
  494.             else if (itsTable->GetSelect(true,&aCell)) {
  495.                 thereIsASelection = true;
  496.             }
  497.     ResetGopher();
  498.     switch (theCommand) {
  499.  
  500.         case cmdAddCFile:
  501.                 gApplication->ChooseSourceFile(&theFile);
  502.                 if (theFile.good) {
  503.                     AddSourceFile(&theFile);
  504.                 }
  505.                 break;
  506.         case cmdRemove:
  507.             /* Remove the currently selected file */
  508.             if (thereIsASelection) {
  509.                 /* Delete the item from the itsSourceFiles list and
  510.                     the row from the table */
  511.                 itsSourceFiles->Remove(itsSourceFiles->NthItem(aCell.v+1));
  512.                 itsTable->DeleteRow(1,aCell.v);
  513.                 itsTable->DeselectAll(true);
  514.             }
  515.         break;
  516.         case cmdOpenSourceFile:
  517.             if (thereIsASelection) {
  518.                 OSType theSig;
  519.                 CSourceFile *theSourceFile = (CSourceFile *) itsSourceFiles->NthItem(aCell.v+1);
  520.                 theSig = 0;
  521.                 if (theSourceFile->itsKind == H_ResourceFile) theSig = 'RSED';
  522.                 else if (theSourceFile->itsKind == H_SourceFile) theSig = 'ALFA';
  523.                 else theSig = 0;
  524.                 gApplication->InspectSystem();
  525.                 if (gSystem.hasAppleEvents && theSig)
  526.                 {
  527.                     AERecord ae;
  528.                     AEDescList aeList;
  529.                     AEDesc docDesc;
  530.                     AEAddressDesc alfa;
  531.                     AliasHandle withThis;
  532.                     OSErr err;
  533.                     FSSpec theSpec;
  534.                     
  535.                     FSMakeFSSpec(theSourceFile->theFile->volNum,
  536.                                 theSourceFile->theFile->dirID,
  537.                                 theSourceFile->theFile->name,
  538.                                 &theSpec);
  539.                     err = AECreateDesc(typeApplSignature,(Ptr) &theSig,(Size) sizeof(theSig),&alfa);
  540.                     FailOSErr(err);
  541.                     err = AECreateAppleEvent(kCoreEventClass,kAEOpenDocuments,&alfa,kAutoGenerateReturnID,
  542.                         kAnyTransactionID,&ae);
  543.                     FailOSErr(err);
  544.                     err = AECreateList(NULL,0,FALSE,&aeList);
  545.                     FailOSErr(err);
  546.                     NewAlias(NULL,&theSpec,&withThis);
  547.                     HLock((Handle) withThis);
  548.                     err = AECreateDesc(typeAlias,(Ptr) *withThis, GetHandleSize((Handle) withThis),
  549.                         &docDesc);
  550.                     FailOSErr(err);
  551.                     HUnlock((Handle) withThis);
  552.                     err = AEPutDesc(&aeList,0,&docDesc);
  553.                     FailOSErr(err);
  554.                     err = AEPutParamDesc(&ae,keyDirectObject,&aeList);
  555.                     FailOSErr(err);
  556.                     err = AESend(&ae,NULL,kAENoReply,kAENormalPriority,0,NULL,NULL);
  557.                     FailOSErr(err);
  558.                     if (!err) {
  559.                         ProcessSerialNumber process;
  560.                         ProcessInfoRec InfoRec;
  561.                         FSSpec theSpec;
  562.                         if (FindAProcess(theSig,&process,&InfoRec,&theSpec)) {
  563.                             SetFrontProcess(&process);
  564.                         }
  565.                     }
  566.                 }
  567.             }
  568.         break;
  569.         case cmdCompile:
  570.             /* Compile the currently selected file */
  571.             if (thereIsASelection) {
  572.                 CSourceFile *theFile;
  573.                 theFile = ((CSourceFile *) itsSourceFiles->NthItem(aCell.v+1));
  574.                 if (theFile->itsKind == H_SourceFile) {
  575.                     theFile->Compile();
  576.                 }
  577.             }
  578.         break;
  579.         case cmdSetProjectInfo:
  580.             DoSetProjectInfo();
  581.         break;
  582.         case cmdOptions:
  583.             DoOptions(itsOptions);
  584.         break;
  585.         case cmdWarnings:
  586.             DoWarnings(itsOptions,itsWarnings);
  587.         break;
  588.         case cmdSave:
  589.             SysBeep(1);
  590.             break;
  591.         case cmdCloseProject:
  592.         case cmdClose:
  593.             this->Close(false);
  594.             break;
  595.     
  596.         case cmdBringUpToDate:
  597.             BringUpToDate();
  598.             break;
  599.         case cmdRun:
  600.             RunApp();
  601.             break;
  602.         case cmdBuildApplication:
  603.             Link();
  604.             break;
  605.         case cmdCheckLink:
  606.             CheckLink();
  607.             break;
  608.         case cmdClean:
  609.             Clean();
  610.             break;
  611.  
  612.         default:    inherited::DoCommand(theCommand);
  613.                     break;
  614.     }
  615. }
  616.  
  617.  
  618. /***
  619.  * UpdateMenus
  620.  *
  621.  *  In this method you can enable menu commands that apply when
  622.  *  your document is active.
  623.  *
  624.  *  Be sure to call the inherited method to get the default behavior.
  625.  *  The inherited method enables these commands: cmdClose, cmdSaveAs,
  626.  *  cmdSave, cmdRevert, cmdPageSetup, cmdPrint, cmdUndo.
  627.  *
  628. ***/
  629.  
  630.  void CHarvestDoc::UpdateMenus()
  631.  
  632.  {
  633.      Cell aCell = {0,0};
  634.      Boolean thereIsASelection = false;
  635.     CSourceFile *theSourceFile;
  636.     inherited::UpdateMenus();
  637.  
  638.     /* Enable your menu commands here (enable each one with a call to   
  639.        gBartender->EnableCmd(command_number)).  
  640.     */                      
  641.     gBartender->EnableCmd(cmdAddCFile);
  642.     /* others in the Sources menu will be enabled when there are actually
  643.         things in the project */
  644.     if (itsTable->GetSelect(false,&aCell)) {
  645.         thereIsASelection = true;
  646.     }
  647.     else if (itsTable->GetSelect(true,&aCell)) {
  648.         thereIsASelection = true;
  649.     }
  650.     theSourceFile = (CSourceFile *) itsSourceFiles->NthItem(aCell.v+1);
  651.     if (thereIsASelection) {
  652.         gBartender->EnableCmd(cmdRemove);
  653.         gBartender->DisableCmd(cmdGetInfo);
  654.         if (theSourceFile->itsKind == H_SourceFile) {
  655.             /* TODO enable these when they are implemented */
  656.             gBartender->DisableCmd(cmdCheckSyntax);
  657.             gBartender->DisableCmd(cmdPreprocess);
  658.             gBartender->EnableCmd(cmdCompile);
  659.             gBartender->EnableCmd(cmdOpenSourceFile);
  660.         }
  661.         else if (theSourceFile->itsKind == H_ResourceFile) {
  662.             gBartender->EnableCmd(cmdOpenSourceFile);
  663.         }
  664.     }
  665.         
  666.     gBartender->DisableCmd(cmdSave);   
  667.     gBartender->DisableCmd(cmdSaveAs);
  668.     gBartender->DisableCmd(cmdNewProject);
  669.     gBartender->DisableCmd(cmdNew);
  670.     gBartender->DisableCmd(cmdOpenProject);
  671.     gBartender->DisableCmd(cmdOpen);
  672.     gBartender->EnableCmd(cmdOptions);
  673.     gBartender->EnableCmd(cmdWarnings);
  674.     gBartender->EnableCmd(cmdCloseProject);
  675.     gBartender->EnableCmd(cmdClose);
  676.     gBartender->EnableCmd(cmdSetProjectInfo);
  677.     gBartender->EnableCmd(cmdClean);
  678.     gBartender->EnableCmd(cmdBuildApplication);
  679.     gBartender->DisableCmd(cmdCheckLink);
  680.     gBartender->EnableCmd(cmdBringUpToDate);
  681.     gBartender->EnableCmd(cmdRun);
  682.     gBartender->DisableCmd(cmdPrint);
  683.  }
  684.  
  685.  
  686. /***
  687.  * FSNewFile
  688.  *
  689.  ***/
  690. void CHarvestDoc::FSNewFile(char *name, short vRefNum, long dirID)
  691.  
  692. {    
  693.     Str255  wTitle;     /* Window title string.         */
  694.     short   wCount;     /* Index number of new window.  */
  695.     Str255  wNumber;    /* Index number as a string.    */
  696.     CDataFile *theFile;
  697.     
  698.         /**
  699.          **    BuildWindow() is the method that
  700.          **    does the work of creating a window.
  701.          ** Its parameter should be the data that
  702.          **    you want to display in the window.
  703.          **    Since this is a new window, there's nothing
  704.          **    to display.
  705.          **
  706.          **/
  707.  
  708.     BuildWindow(NULL);
  709.  
  710.     theFile = new(CDataFile);
  711.     theFile->IDataFile();
  712.     theFile->SpecifyHFS((unsigned char *) name,vRefNum,dirID);
  713.     
  714.     
  715.         /**
  716.          ** Append an index number to the
  717.          ** default name of the window.
  718.          **/
  719.     theFile->GetName(wTitle);
  720.     if (theFile->ExistsOnDisk())
  721.         theFile->ThrowOut();
  722.     theFile->CreateNew(gSignature,'Hprj');
  723.     theFile->Open(fsWrPerm);
  724.  
  725.     itsFile = theFile;
  726.     itsWindow->SetTitle(wTitle);
  727.  
  728.         /**
  729.          **    Send the window a Select() message to make
  730.          **    it the active window.
  731.          **/
  732.     
  733.     itsWindow->Select();
  734.     
  735.     if (gApplication->StdLibVol || gApplication->StdLibDir) {
  736.         AddLibraryFileHFS("\pInterface.o",gApplication->StdLibVol,
  737.             gApplication->StdLibDir);
  738.         AddLibraryFileHFS("\pRuntime.o",gApplication->StdLibVol,
  739.             gApplication->StdLibDir);
  740.     }
  741. }
  742.  
  743. /***
  744.  * NewFile
  745.  *
  746.  *    When the user chooses New from the File menu, the CreateDocument()
  747.  *    method in your Application class will send a newly created document
  748.  *    this message. This method needs to create a new window, ready to
  749.  *    work on a new document.
  750.  *
  751.  *    Since this method and the OpenFile() method share the code for creating
  752.  *    the window, you should use an auxiliary window-building method.
  753.  *
  754.  ***/
  755. void CHarvestDoc::NewFile(void)
  756.  
  757. {    
  758.     Str255  wTitle;     /* Window title string.         */
  759.     short   wCount;     /* Index number of new window.  */
  760.     Str255  wNumber;    /* Index number as a string.    */
  761.     SFReply macSFReply;
  762.     CDataFile *theFile;
  763.     
  764.         /**
  765.          **    BuildWindow() is the method that
  766.          **    does the work of creating a window.
  767.          ** Its parameter should be the data that
  768.          **    you want to display in the window.
  769.          **    Since this is a new window, there's nothing
  770.          **    to display.
  771.          **
  772.          **/
  773.  
  774.     PickFileName(&macSFReply);
  775.     if (macSFReply.good) {
  776.         BuildWindow(NULL);
  777.     
  778.         theFile = new(CDataFile);
  779.         theFile->IDataFile();
  780.         theFile->SFSpecify(&macSFReply);
  781.         
  782.         
  783.             /**
  784.              ** Append an index number to the
  785.              ** default name of the window.
  786.              **/
  787.         theFile->GetName(wTitle);
  788.         if (theFile->ExistsOnDisk())
  789.             theFile->ThrowOut();
  790.         theFile->CreateNew(gSignature,'Hprj');
  791.         theFile->Open(fsWrPerm);
  792.     
  793.         itsFile = theFile;
  794.         itsWindow->SetTitle(wTitle);
  795.     
  796.             /**
  797.              **    Send the window a Select() message to make
  798.              **    it the active window.
  799.              **/
  800.         
  801.         itsWindow->Select();
  802.         
  803.         if (gApplication->StdLibVol || gApplication->StdLibDir) {
  804.             AddLibraryFileHFS("\pInterface.o",gApplication->StdLibVol,
  805.                 gApplication->StdLibDir);
  806.             AddLibraryFileHFS("\pRuntime.o",gApplication->StdLibVol,
  807.                 gApplication->StdLibDir);
  808.         }
  809.     }
  810. }
  811.  
  812.  
  813. /***
  814.  * OpenFile
  815.  *
  816.  *    When the user chooses Open… from the File menu, the OpenDocument()
  817.  *    method in your Application class will let the user choose a file
  818.  *    and then send a newly created document this message. The information
  819.  *    about the file is in the SFReply record.
  820.  *
  821.  *    In this method, you need to open the file and display its contents
  822.  *    in a window. This method uses the auxiliary window-building method.
  823.  *
  824.  ***/
  825.  
  826. void CHarvestDoc::OpenFile(SFReply *macSFReply)
  827.  
  828. {
  829.     CDataFile    *theFile;
  830.     Handle        theData = NULL;
  831.     Str63        theName;
  832.     FInfo        fileInfo;
  833.     OSErr        theError;
  834.     
  835.     TRY
  836.     {
  837.     
  838.             /**
  839.              ** Create a file and send it a SFSpecify()
  840.              **    message to set up the name, volume, and
  841.              **    directory.
  842.              **
  843.              **/
  844.     
  845.         theFile = new(CDataFile);
  846.         theFile->IDataFile();
  847.         theFile->SFSpecify(macSFReply);
  848.         theFile->GetMacFileInfo(&fileInfo);
  849.         if (fileInfo.fdType != 'Hprj') {
  850.             Failure(kSilentErr,0);
  851.         }
  852.             /**
  853.              **    Be sure to set the instance variable
  854.              **    so other methods can use the file if they
  855.              **    need to. This is especially important if
  856.              **    you leave the file open in this method.
  857.              **    If you close the file after reading it, you
  858.              **    should be sure to set itsFile to NULL.
  859.              **
  860.              **/
  861.     
  862.         itsFile = theFile;
  863.  
  864.             /**
  865.              **    Send the file an Open() message to
  866.              **    open it. You can use the ReadSome() or
  867.              **    ReadAll() methods to get the contents of the file.
  868.              **
  869.              **/
  870.     
  871.         theFile->Open(fsRdWrPerm);
  872.         
  873.             /**
  874.              **    Make sure that the memory request to read
  875.              **    the data from the file doesn't use up any
  876.              **    of our rainy day fund and that the GrowMemory()
  877.              **    method (in the application) knows that it's OK
  878.              **    if we couldn't get enough memory.
  879.              **
  880.              **/
  881.     
  882.     
  883.         theData = theFile->ReadAll();     /* ReadAll() creates the handle */
  884.         
  885.         if (!theData) {
  886.             Failure(kSilentErr,0);
  887.         }
  888.         
  889.         BuildWindow(theData);
  890.     
  891.         if (StdAppName[0] == 0) {
  892.             itsFile->GetName(StdAppName);
  893.         }
  894.         if (StdAppName[StdAppName[0]] == 'π') {
  895.             if (StdAppName[StdAppName[0]-1] == '.') {
  896.                 StdAppName[0] -= 2;
  897.             }
  898.             else {
  899.                 StdAppName[0] -= 1;
  900.             }
  901.         }
  902.             /**
  903.              **    In your application, you'll probably store
  904.              **    the data in some form as an instance variable
  905.              **    in your document class. For this example, there's
  906.              **    no need to save it, so we'll get rid of it.
  907.              **
  908.              **/
  909.     
  910.         DisposHandle(theData);
  911.         theData = NULL;
  912.     
  913.             /**
  914.              **    In this implementation, we leave the file
  915.              **    open. You might want to close it after
  916.              **    you've read in all the data.
  917.              **
  918.              **/
  919.     
  920.         itsFile->GetName(theName);
  921.         itsWindow->SetTitle(theName);
  922.         itsWindow->Select();            /* Don't forget to make the window active */
  923.     }
  924.     
  925.     CATCH
  926.     {
  927.         /*
  928.          * This exception handler will be executed if an exception occurs
  929.          * anywhere within the scope of the TRY block above.
  930.          * You should perform any cleanup of things that won't be needed
  931.          * since the document could not be opened. By convention,
  932.          * the creator of an object is responsible for sending it
  933.          * the Dispose message. This means that we should only dispose
  934.          * of things that would not be taken care of in Dispose.
  935.          * In this case, we just make sure that the Handle theData
  936.          * has been disposed of. The exception will propagate up to
  937.          * CApplications's exception handler, which handles displaying
  938.          * an error alert.
  939.          */
  940.          
  941.          if (theData) DisposHandle( theData);
  942.          
  943.     }
  944.     ENDTRY;
  945. }
  946.  
  947. /***
  948.  * FSOpenFile
  949.  *
  950.  *    When the user chooses Open… from the File menu, the OpenDocument()
  951.  *    method in your Application class will let the user choose a file
  952.  *    and then send a newly created document this message. The information
  953.  *    about the file is in the SFReply record.
  954.  *
  955.  *    In this method, you need to open the file and display its contents
  956.  *    in a window. This method uses the auxiliary window-building method.
  957.  *
  958.  ***/
  959.  
  960. void CHarvestDoc::FSOpenFile(char *name, short vRefNum, long dirID)
  961.  
  962. {
  963.     CDataFile    *theFile;
  964.     Handle        theData = NULL;
  965.     Str63        theName;
  966.     FInfo        fileInfo;
  967.     OSErr        theError;
  968.     
  969.     TRY
  970.     {
  971.     
  972.             /**
  973.              ** Create a file and send it a SFSpecify()
  974.              **    message to set up the name, volume, and
  975.              **    directory.
  976.              **
  977.              **/
  978.     
  979.         theFile = new(CDataFile);
  980.         theFile->IDataFile();
  981.         theFile->SpecifyHFS((unsigned char *) name,vRefNum,dirID);
  982.         theFile->GetMacFileInfo(&fileInfo);
  983.         if (fileInfo.fdType != 'Hprj') {
  984.             gProject = NULL;
  985.             return;
  986.         }
  987.             /**
  988.              **    Be sure to set the instance variable
  989.              **    so other methods can use the file if they
  990.              **    need to. This is especially important if
  991.              **    you leave the file open in this method.
  992.              **    If you close the file after reading it, you
  993.              **    should be sure to set itsFile to NULL.
  994.              **
  995.              **/
  996.     
  997.         itsFile = theFile;
  998.  
  999.             /**
  1000.              **    Send the file an Open() message to
  1001.              **    open it. You can use the ReadSome() or
  1002.              **    ReadAll() methods to get the contents of the file.
  1003.              **
  1004.              **/
  1005.     
  1006.         theFile->Open(fsRdWrPerm);
  1007.         
  1008.             /**
  1009.              **    Make sure that the memory request to read
  1010.              **    the data from the file doesn't use up any
  1011.              **    of our rainy day fund and that the GrowMemory()
  1012.              **    method (in the application) knows that it's OK
  1013.              **    if we couldn't get enough memory.
  1014.              **
  1015.              **/
  1016.     
  1017.     
  1018.         theData = theFile->ReadAll();     /* ReadAll() creates the handle */
  1019.         
  1020.         if (!theData) {
  1021.             Failure(kSilentErr,0);
  1022.         }
  1023.         
  1024.         BuildWindow(theData);
  1025.     
  1026.         if (StdAppName[0] == 0) {
  1027.             itsFile->GetName(StdAppName);
  1028.         }
  1029.         if (StdAppName[StdAppName[0]] == 'π') {
  1030.             if (StdAppName[StdAppName[0]-1] == '.') {
  1031.                 StdAppName[0] -= 2;
  1032.             }
  1033.             else {
  1034.                 StdAppName[0] -= 1;
  1035.             }
  1036.         }
  1037.             /**
  1038.              **    In your application, you'll probably store
  1039.              **    the data in some form as an instance variable
  1040.              **    in your document class. For this example, there's
  1041.              **    no need to save it, so we'll get rid of it.
  1042.              **
  1043.              **/
  1044.     
  1045.         DisposHandle(theData);
  1046.         theData = NULL;
  1047.     
  1048.             /**
  1049.              **    In this implementation, we leave the file
  1050.              **    open. You might want to close it after
  1051.              **    you've read in all the data.
  1052.              **
  1053.              **/
  1054.     
  1055.         itsFile->GetName(theName);
  1056.         itsWindow->SetTitle(theName);
  1057.         itsWindow->Select();            /* Don't forget to make the window active */
  1058.     }
  1059.     
  1060.     CATCH
  1061.     {
  1062.         /*
  1063.          * This exception handler will be executed if an exception occurs
  1064.          * anywhere within the scope of the TRY block above.
  1065.          * You should perform any cleanup of things that won't be needed
  1066.          * since the document could not be opened. By convention,
  1067.          * the creator of an object is responsible for sending it
  1068.          * the Dispose message. This means that we should only dispose
  1069.          * of things that would not be taken care of in Dispose.
  1070.          * In this case, we just make sure that the Handle theData
  1071.          * has been disposed of. The exception will propagate up to
  1072.          * CApplications's exception handler, which handles displaying
  1073.          * an error alert.
  1074.          */
  1075.          
  1076.          if (theData) DisposHandle( theData);
  1077.          gProject = NULL;
  1078.          
  1079.     }
  1080.     ENDTRY;
  1081. }
  1082.  
  1083.  
  1084.  
  1085. /***
  1086.  * BuildWindow
  1087.  *
  1088.  *    This is the auxiliary window-building method that the
  1089.  *    NewFile() and OpenFile() methods use to create a window.
  1090.  *
  1091.  *    In this implementation, the argument is the data to display.
  1092.  *
  1093.  ***/
  1094.  
  1095. void CHarvestDoc::BuildWindow (Handle theData)
  1096.  
  1097. {
  1098.     CScrollPane        *theScrollPane;
  1099.     CHarvestPane    *theMainPane;
  1100.     Rect theRect = {75,175,300,175};
  1101.  
  1102.         /**
  1103.          **    First create the window and initialize
  1104.          **    it. The first argument is the resource ID
  1105.          **    of the window. The second argument specifies
  1106.          **    whether the window is a floating window.
  1107.          **    The third argument is the window's enclosure; it
  1108.          **    should always be gDesktop. The last argument is
  1109.          **    the window's supervisor in the Chain of Command;
  1110.          **    it should always be the Document object.
  1111.          **
  1112.          **/
  1113.     itsWindow = new(CWindow);
  1114.     itsWindow->IWindow(WINDHarvest, FALSE, gDesktop, this);
  1115.     
  1116.         /**
  1117.          **    After you create the window, you can use the
  1118.          **    SetSizeRect() message to set the window’s maximum
  1119.          **    and minimum size. Be sure to set the max & min
  1120.          **    BEFORE you send a PlaceNewWindow() message to the
  1121.          **    decorator.
  1122.          **
  1123.          ** The default minimum is 100 by 100 pixels. The
  1124.          **    default maximum is the bounds of GrayRgn() (The
  1125.          **    entire display area on all screens.)
  1126.          **
  1127.          ** We'll use the defaults.
  1128.          **
  1129.          **/
  1130.     itsWindow->SetSizeRect(&theRect);
  1131.         /**
  1132.          ** Our window will contain a ScrollPane,
  1133.          ** which in turn will contain a Panorama.
  1134.          ** Now, let's create the ScrollPane.
  1135.          **/
  1136.  
  1137.     theScrollPane = new(CScrollPane);
  1138.     
  1139.         /**
  1140.          **    You can initialize a scroll pane two ways:
  1141.          **        1. You can specify all the values
  1142.          **           right in your code, like this.
  1143.          **        2. You can create a ScPn resource and
  1144.          **           initialize the pane from the information
  1145.          **           in the resource.
  1146.          **
  1147.          **/
  1148.  
  1149.     theScrollPane->IScrollPane(itsWindow, this, 10, 10, 0, 0,
  1150.                                 sizELASTIC, sizELASTIC,
  1151.                                 TRUE, TRUE, TRUE);
  1152.  
  1153.         /**
  1154.          **    The FitToEnclFrame() method makes the
  1155.          **    scroll pane be as large as its enclosure.
  1156.          **    In this case, the enclosure is the window,
  1157.          **    so the scroll pane will take up the entire
  1158.          **    window.
  1159.          **
  1160.          **/
  1161.  
  1162.     theScrollPane->FitToEnclFrame(TRUE, TRUE);
  1163.  
  1164.  
  1165.         /**
  1166.          **    itsMainPane is the document's focus
  1167.          **    of attention. Some of the standard
  1168.          **    classes (particularly CPrinter) rely
  1169.          **    on itsMainPane pointing to the main
  1170.          **    pane of your window.
  1171.          **
  1172.          **    itsGopher specifies which object
  1173.          ** should become the gopher when the document
  1174.          ** becomes active. By default
  1175.          **    the document becomes the gopher. It’s
  1176.          **    likely that your main pane handles commands
  1177.          **    so you’ll almost always want to set itsGopher
  1178.          **    to point to the same object as itsMainPane.
  1179.          **
  1180.          **    Note that the main pane is the
  1181.          **    panorama in the scroll pane and not
  1182.          **    the scroll pane itself.
  1183.          **
  1184.          **/
  1185.  
  1186.     theMainPane = new(CHarvestPane);
  1187.     theMainPane->IHarvestPane(theScrollPane, this);
  1188.         // finally initialize the table
  1189.         // insert some rows and columns into the new table
  1190.     
  1191.     itsMainPane = itsTable = theMainPane;
  1192.     itsTable->AddRow( 0, -1);
  1193.     itsTable->AddCol( 1, -1);
  1194.     itsTable->SetDblClickCmd(cmdOpenSourceFile);
  1195.     itsGopher = theMainPane;
  1196.     
  1197.         /**    The FitToEnclosure() method makes the pane
  1198.          **    fit inside the enclosure. The inside (or
  1199.          **    interior) of a scroll pane is defined as
  1200.          **    the area inside the scroll bars.
  1201.          **/
  1202.  
  1203.     theMainPane->FitToEnclosure(TRUE, TRUE);
  1204.  
  1205.         /**
  1206.          **    Send the scroll pane an InstallPanorama()
  1207.          ** message to associate the panorama with 
  1208.          ** the scroll pane.
  1209.          **
  1210.          **/
  1211.  
  1212.     theScrollPane->InstallPanorama(theMainPane);
  1213.     
  1214.         /**
  1215.          **    The Decorator is a global object that takes care
  1216.          **    of placing and sizing windows on the screen.
  1217.          **    You don't have to use it.
  1218.          **
  1219.          **/
  1220.  
  1221.     gDecorator->PlaceNewWindow(itsWindow);
  1222.             
  1223.     itsWindow->Select();
  1224.  
  1225.     if (theData) {
  1226.         if (GetHandleSize(theData))
  1227.             ReadFromHandle(theData);
  1228.     }
  1229. }
  1230.  
  1231. #define HWriteShort(h,i,val) if ((i+2)>=dataSize) SetHandleSize(h,dataSize*=2);BlockMove(&val,&((*(h))[(i)]),sizeof(short));i+=sizeof(short);
  1232. #define HWriteLong(h,i,val) if ((i+4)>=dataSize) SetHandleSize(h,dataSize*=2);BlockMove(&val,&((*(h))[(i)]),sizeof(long));i+=sizeof(long);
  1233.  
  1234. #define HReadShort(h,i,val) BlockMove(&((*(h))[(i)]),&val,sizeof(short));i+=sizeof(short);
  1235. #define HReadLong(h,i,val)  BlockMove(&((*(h))[(i)]),&val,sizeof(long));i+=sizeof(long);
  1236.  
  1237. #ifdef Undefined
  1238. #define HWriteShort(h,i,val) (*(h))[(i)] = HiByte((val));(*(h))[(i)+1] = LoByte((val));i+=2;
  1239. #define HWriteLong(h,i,val)    (*(h))[(i)] = HiByte((HiShort((val)))); \
  1240.                             (*(h))[(i)+1] = LoByte((HiShort((val)))); \
  1241.                             (*(h))[(i)+2] = HiByte((LoShort((val)))); \
  1242.                             (*(h))[(i)+3] = LoByte((LoShort((val))));i+=4;
  1243. #endif
  1244. #define HWriteCString(h,i,s) if ((i+strlen(s))>=dataSize) SetHandleSize(h,dataSize*=2);strcpy(&((*(h))[(i)]),s);i+=strlen(s)+1;
  1245. #define HWritePString(h,i,s) if ((i+*s)>=dataSize) SetHandleSize(h,dataSize*=2);CopyPString(s,((unsigned char *) &((*(h))[(i)])));i+=*s+1;
  1246.  
  1247. #ifdef Undefined
  1248. #define HReadShort(h,i,val) val = ((((int) ((*(h))[(i)])) << 8) | ((int) ((*(h))[(i)+1])));i+=2;
  1249. #define HReadLong(h,i,val) val = (((int) ((*(h))[(i)])) << 24) | (((int) ((*(h))[(i)+1])) << 16) \
  1250.                                 | (((int) ((*(h))[(i)+2])) << 8) | (((int) ((*(h))[(i)+3])));i+=4;
  1251. #endif
  1252.                                 
  1253. #define HReadCString(h,i,s) strcpy(s,&((*(h))[(i)]),s);i+=strlen(s)+1;
  1254. #define HReadPString(h,i,s) CopyPString(((unsigned char *) &((*(h))[(i)])),s);i+=*s+1;
  1255.  
  1256. Handle CHarvestDoc::WriteToHandle(void)
  1257. {
  1258.     long ndx = 0;
  1259.     long i;
  1260.     Handle theData;
  1261.     CSourceFile *aFile;
  1262.     Handle aHandle;
  1263.     long dataSize = 4000;    /* Danger - this should not be hard coded */
  1264.     long k2;
  1265.     short CountSourceFiles;
  1266.     
  1267.     theData = NewHandleClear(dataSize);
  1268.  
  1269.     aHandle = (Handle) itsOptions;
  1270.     BlockMove(*aHandle,(*theData + ndx),ndx += GetHandleSize(aHandle));
  1271.     
  1272.     CountSourceFiles = itsSourceFiles->GetNumItems();
  1273.     HWriteShort(theData,ndx,CountSourceFiles);
  1274.     HWriteLong (theData,ndx,itsSignature);
  1275.     HWriteLong (theData,ndx,itsPartition);
  1276.     HWriteShort(theData,ndx,StdAppVol);
  1277.     HWriteLong (theData,ndx,StdAppDir);
  1278.     HWritePString(theData,ndx,StdAppName);
  1279.     
  1280.     for (i=1;i<=CountSourceFiles;i++) {
  1281.         short k;
  1282.         aFile = (CSourceFile *) itsSourceFiles->NthItem(i);
  1283.         if (aFile->itsOptions) {
  1284.             k = 1;
  1285.             HWriteShort(theData,ndx,k);
  1286.             aHandle = (Handle) aFile->itsOptions;
  1287.             BlockMove(*aHandle,(*theData + ndx),ndx += GetHandleSize(aHandle));
  1288.         }
  1289.         else {
  1290.             k = 0;
  1291.             HWriteShort(theData,ndx,k);
  1292.         }
  1293.         HWriteShort(theData,ndx,aFile->itsKind);
  1294.         HWriteShort(theData,ndx,aFile->theFile->volNum);
  1295.         HWriteLong(theData,ndx,aFile->theFile->dirID);
  1296.         HWritePString(theData,ndx,aFile->theFile->name);
  1297.     }
  1298.     
  1299.     k2 = strlen(itsPrefix);
  1300.     HWriteLong(theData,ndx,k2);
  1301.     HWriteCString(theData,ndx,itsPrefix);
  1302.     k2 = 0;
  1303.     HWriteLong(theData,ndx,k2);
  1304.  
  1305.     return theData;
  1306. }
  1307.  
  1308. /*
  1309.     This function reads the Harvest C project file format
  1310. */
  1311. void CHarvestDoc::ReadFromHandle(Handle theData)
  1312. {
  1313.     long ndx = 0;
  1314.     long i;
  1315.     Handle aHandle;
  1316.     short CountSourceFiles;
  1317.     short flag;
  1318.     short vol;
  1319.     long dirID;
  1320.     long scratch;
  1321.     Str63 name;
  1322.     
  1323.     StdAppVol = itsFile->volNum;
  1324.     StdAppDir = itsFile->dirID;
  1325.     
  1326.     aHandle = (Handle) itsOptions;
  1327.     BlockMove((*theData + ndx),*aHandle,ndx += GetHandleSize(aHandle));
  1328.  
  1329.     HReadShort(theData,ndx,CountSourceFiles);
  1330.     HReadLong (theData,ndx,itsSignature);
  1331.     HReadLong (theData,ndx,itsPartition);
  1332.     HReadShort(theData,ndx,StdAppVol);
  1333.     HReadLong (theData,ndx,StdAppDir);
  1334.     HReadPString(theData,ndx,StdAppName);
  1335.     
  1336.     for (i=1;i<=CountSourceFiles;i++) {
  1337.         short kind;
  1338.         HReadShort(theData,ndx,flag);
  1339.         if (flag) {
  1340.             aHandle = (Handle) new CHarvestOptions;
  1341.             BlockMove(*aHandle,(*theData + ndx),ndx += GetHandleSize(aHandle));
  1342.         }
  1343.         HReadShort(theData,ndx,kind);
  1344.         HReadShort(theData,ndx,vol);
  1345.         HReadLong(theData,ndx,dirID);
  1346.         HReadPString(theData,ndx,name);
  1347.  
  1348.         /* the following two lines were added to fix the problem with project files
  1349.             not working on other machines.  These lines force a restriction: the C
  1350.             source files must be in the same folder as the project file.
  1351.         */
  1352.         vol = itsFile->volNum;
  1353.         dirID = itsFile->dirID;
  1354.  
  1355.         if (kind == H_LibraryFile)
  1356.             AddLibraryFileHFS(name,vol,dirID);
  1357.         else if (kind == H_ResourceFile)
  1358.             AddResourceFileHFS(name,vol,dirID);
  1359.         else
  1360.             AddSourceFileHFS(name,vol,dirID);
  1361.     }
  1362.     
  1363.     HReadLong(theData,ndx,scratch);
  1364.     itsPrefix = (char *) icemalloc(scratch);
  1365.     HReadCString(theData,ndx,itsPrefix);
  1366.     HReadLong(theData,ndx,scratch);
  1367. }
  1368.  
  1369. /******************************************************************************
  1370.  Close {OVERRIDE}
  1371.  
  1372.         Close a Document
  1373.  ******************************************************************************/
  1374.  
  1375. Boolean    CHarvestDoc::Close(
  1376.     Boolean        quitting)                /* Is this part of a quit sequence?    */
  1377. {
  1378.     /* Ignore quitting -- We always save the file. */
  1379.  
  1380.     Handle theData;
  1381.     
  1382.         if (!itsFile) {
  1383.             /* We need to specify a file */
  1384.         }
  1385.         else {
  1386.             theData = WriteToHandle();
  1387.             ((CDataFile *) itsFile)->SetMark(0,fsFromStart);
  1388.             ((CDataFile *) itsFile)->WriteAll(theData);
  1389.             if (itsFile != NULL) {            /* Yes. Close associated file.        */
  1390.                 itsFile->Close();
  1391.                 itsFile = NULL;
  1392.             }
  1393.             DisposHandle(theData);
  1394.         }
  1395.     
  1396.         inherited::Close(quitting);
  1397.         gProject = NULL;
  1398.         return(TRUE);                    /* Document has been closed            */
  1399.         
  1400. }
  1401.     
  1402. /***
  1403.  * DoSave
  1404.  *
  1405.  *    This method handles what happens when the user chooses Save from the
  1406.  *    File menu. This method should return TRUE if the file save was successful.
  1407.  *    If there is no file associated with the document, you should send a
  1408.  *    DoSaveFileAs() message.
  1409.  *
  1410.  ***/
  1411.  
  1412. Boolean CHarvestDoc::DoSave(void)
  1413.  
  1414. {
  1415.         /**
  1416.          **    If you closed your file in your NewFile() method,
  1417.          **    you'll need a different way than this to determine
  1418.          **    if there's a file associated with your document.
  1419.          **
  1420.          **/
  1421.  
  1422.     if (itsFile == NULL)
  1423.         return(DoSaveFileAs());
  1424.     else {
  1425.             
  1426.         /**
  1427.          **    In your application, this is where you'd
  1428.          **    write out your file. if you left it open,
  1429.          **    send the WriteSome() or WriteAll() mesages
  1430.          **    to itsFile.
  1431.          **
  1432.          **/
  1433.             
  1434.         dirty = FALSE;                    /* Document is no longer dirty        */
  1435.         gBartender->DisableCmd(cmdSave);
  1436.         return(TRUE);                    /* Save was successful                */
  1437.     }
  1438. }
  1439.  
  1440.  
  1441. /***
  1442.  * DoSaveAs
  1443.  *
  1444.  *    This method handles what happens when the user chooses Save As… from
  1445.  *    File menu. The default DoCommand() method for documents sends a DoSaveFileAs()
  1446.  *    message which displays a standard put file dialog and sends this message.
  1447.  *    The SFReply record contains all the information about the file you're about
  1448.  *    to create.
  1449.  *
  1450.  ***/
  1451.  
  1452. Boolean CHarvestDoc::DoSaveAs(SFReply *macSFReply)
  1453.  
  1454. {
  1455.         /**
  1456.          **    If there's a file associated with this document
  1457.          **    already, close it. The Dispose() method for files
  1458.          **    sends a Close() message to the file before releasing
  1459.          **    its memory.
  1460.          **
  1461.          **/
  1462.          
  1463.     if (itsFile != NULL)
  1464.         itsFile->Dispose();
  1465.  
  1466.  
  1467.         /**
  1468.          **    Create a new file, and then save it normally.
  1469.          **
  1470.          **/
  1471.  
  1472.     itsFile = new(CDataFile);
  1473.     ((CDataFile *)itsFile)->IDataFile();
  1474.     itsFile->SFSpecify(macSFReply);
  1475.     itsFile->CreateNew(gSignature, 'TEXT');
  1476.     itsFile->Open(fsRdWrPerm);
  1477.     
  1478.     itsWindow->SetTitle(macSFReply->fName);
  1479.  
  1480.     return( DoSave() );
  1481. }
  1482.  
  1483.  
  1484. /***
  1485.  * DoRevert
  1486.  *
  1487.  *    If your application supports the Revert command, this method
  1488.  *    should close the current file (without writing anything out)
  1489.  *    and read the last saved version of the file.
  1490.  *
  1491.  ***/
  1492.  
  1493. void CHarvestDoc::DoRevert(void)
  1494.  
  1495. {
  1496. }
  1497.  
  1498. Boolean CHarvestDoc::BringUpToDate(void) {
  1499.     int CountSourceFiles;
  1500.     int i;
  1501.     CSourceFile *aFile;
  1502.     Boolean result;
  1503.     
  1504.     result = TRUE;
  1505.  
  1506.     CountSourceFiles = itsSourceFiles->GetNumItems();
  1507.     for (i=1;i<=CountSourceFiles;i++) {
  1508.         aFile = (CSourceFile *) itsSourceFiles->NthItem(i);
  1509.         if (aFile->itsKind == H_SourceFile) {
  1510.             if (aFile->GetSourceModDate() >= aFile->GetObjectModDate()) {
  1511.                 if (!aFile->Compile()) {
  1512.                     result = FALSE;
  1513.                 }
  1514.             }
  1515.         }
  1516.     }
  1517.     return result;
  1518. }
  1519.  
  1520. void
  1521. CopyAllResources(CSourceFile *aFile,short theApp)
  1522. {
  1523.         /* Now we copy all resources from theResFile to theApp */
  1524.         short typeCount;
  1525.         short resCount;
  1526.         short j;
  1527.         short k;
  1528.         ResType aType;
  1529.         Handle aRez;
  1530.         Handle dupRez;
  1531.         short resID;
  1532.         Str255 resName;
  1533.         short theResFile;
  1534.         ResType type2;
  1535.         short resAttrs;
  1536.  
  1537.         theResFile = HOpenResFile(aFile->theFile->volNum,aFile->theFile->dirID,aFile->theFile->name,1);
  1538.         UseResFile(theResFile);
  1539.         typeCount = Count1Types();
  1540.         for (j=1;j<=typeCount;j++) {
  1541.             UseResFile(theResFile);
  1542.             Get1IndType(&aType,j);
  1543.             resCount = Count1Resources(aType);
  1544.             for (k=1;k<=resCount;k++) {
  1545.                 UseResFile(theResFile);
  1546.                 aRez = Get1IndResource(aType,k);
  1547.                 GetResInfo(aRez,&resID,&type2,resName);
  1548.                 resAttrs = GetResAttrs(aRez);
  1549.                 DetachResource(aRez);
  1550.                 UseResFile(theApp);
  1551.                 dupRez = Get1Resource(aType,resID);
  1552.                 if (!dupRez) {
  1553.                     AddResource(aRez,aType,resID,resName);
  1554.                     SetResAttrs(aRez,resAttrs);
  1555.                     ChangedResource(aRez);
  1556.                 }
  1557.             }
  1558.         }
  1559.         CloseResFile(theResFile);
  1560. }
  1561.  
  1562. Boolean CHarvestDoc::DoLink(void)
  1563. {
  1564. #ifdef HDEBUG
  1565.     extern FILE *dumpFile;
  1566. #endif
  1567.  
  1568.     LinkerFileVia_t                 curf;
  1569.     int                             UserAbort = 0;
  1570.     InFileVia_t                     curin;
  1571.     LinkerFileVia_t                 files = NULL;
  1572.  
  1573.     char                            objname[64];
  1574.     char                            msg[128];
  1575.     char                            err[64];
  1576.     char                            errname[64];
  1577.     CursHandle                      curs;
  1578.     Str63 fname;
  1579.     int CountSourceFiles;
  1580.     int i;
  1581.     CDataFile *objFile;
  1582.     CSourceFile *aFile;
  1583.     CWindow *theWindow;
  1584.     extern unsigned short NextSegID;
  1585.     char mesg[64];
  1586.  
  1587.     LinkErrorCount = 0;
  1588.     
  1589.     curf = NULL;
  1590.  
  1591. #ifdef HDEBUG
  1592.     dumpFile = fopen("Harvest C Debug Info","w");
  1593. #endif
  1594.  
  1595.     gCurSourceFile = NULL;
  1596.     gErrs = new CErrorLog;
  1597.     gErrs->IErrorLog();
  1598.     gErrs->BeginDialog();
  1599.  
  1600.     UserAbort = 0;
  1601.     
  1602.     gApplication->SpinCursor();
  1603.     
  1604.     NextSegID = 2;
  1605.  
  1606.       theWindow = gErrs->GetWindow();
  1607.     sprintf(mesg,"Linking %#s",StdAppName);
  1608. #ifdef HDEBUG
  1609.     fprintf(dumpFile,"%s\n",mesg);
  1610. #endif
  1611.     c2pstr(mesg);
  1612.     theWindow->SetTitle((unsigned char *) mesg);
  1613.  
  1614.     CountSourceFiles = itsSourceFiles->GetNumItems();
  1615.     for (i=1;i<=CountSourceFiles;i++) {
  1616.         gApplication->SpinCursor();
  1617.         aFile = (CSourceFile *) itsSourceFiles->NthItem(i);
  1618.         if (aFile->itsKind != H_ResourceFile) {
  1619.             objFile = aFile->GetObjectFile();
  1620.             curf = NULL;
  1621.             if (objFile) {
  1622.                 CopyPString(objFile->name,fname);
  1623.                 p2cstr(fname);
  1624.                    curf = ReadObjectFile((char *) fname, objFile->volNum, objFile->dirID);
  1625.             }
  1626.             if (curf) {
  1627.                 Via(curf)->next = files;
  1628.                 files = curf;
  1629.             } else {
  1630.                 objFile->GetName((unsigned char *) objname);
  1631.                 p2cstr(objname);
  1632.                 sprintf(err, "Unable to access file %s", objname);
  1633.                 LinkerError(err);
  1634.             }
  1635.         }
  1636.     }
  1637.     if (files && !LinkErrorCount) {
  1638.         ResolveAllReferences(files);
  1639.         /* TODO Smart link */
  1640.         AssignMPWOffsets(files);
  1641.         AdjustAllReferences(files);
  1642.     }
  1643.     if (files && !LinkErrorCount) {
  1644.         Str63 cname;
  1645.         CopyPString(StdAppName,cname);
  1646.         p2cstr(cname);
  1647.         gErrs->Hprintf("References resolved ok");
  1648.         if (FlushLink((char *) cname, StdAppVol, StdAppDir, files)) {
  1649.             short theApp;
  1650.             short theResFile;
  1651.             theApp = HOpenResFile(StdAppVol, StdAppDir, StdAppName, 2);
  1652.             if (theApp == -1) {
  1653.                 LinkerError("Couldn't open app file for adding resources");
  1654.             }
  1655.             else {
  1656.                 for (i=1;i<=CountSourceFiles;i++) {
  1657.                     gApplication->SpinCursor();
  1658.                     aFile = (CSourceFile *) itsSourceFiles->NthItem(i);
  1659.                     if (aFile->itsKind == H_ResourceFile) {
  1660.                         CopyAllResources(aFile,theApp);
  1661.                     }
  1662.                 }
  1663.                 CloseResFile(theApp);
  1664.             }
  1665.         }
  1666.     }
  1667.     else
  1668.         LinkerError("Link errors prevent completion");
  1669.         
  1670.     KillLinkFiles(files);
  1671.     KillSegments(SegmentList);
  1672.     KillModPacks(theDATA.ModuleList);
  1673.     KillImage(theDATA.Image);
  1674.  
  1675. #ifdef HDEBUG
  1676.     fclose(dumpFile);
  1677. #endif
  1678.  
  1679.     InitCursor();
  1680. }
  1681.  
  1682. /******************************************************************************
  1683.  PickAppName
  1684.  
  1685.         Put up a standard put file dialog box to allow the user to
  1686.         specify a new name under which to save the linked application.
  1687.  ******************************************************************************/
  1688.  
  1689. Boolean    CHarvestDoc::PickAppName(void)
  1690. {
  1691.     Point            corner;                /* Top left corner of dialog box    */
  1692.     Str255            origName;            /* Default name for file            */
  1693.     StringHandle    prompt;                /* Prompt string                    */
  1694.     SFReply macSFReply;
  1695.     CDataFile *aFile;
  1696.     FSSpec fileSpec;
  1697.         
  1698.                                         /* Center dialog box on the screen    */
  1699.     FindDlogPosition('DLOG', putDlgID, &corner);
  1700.     
  1701.     CopyPString(StdAppName,origName);
  1702.     
  1703.     prompt = GetString(1000);
  1704.     FailNILRes( prompt);
  1705.     
  1706.     MoveHHi( (Handle) prompt);
  1707.     HLock((Handle) prompt);
  1708.     SFPPutFile(corner, *prompt, origName, NULL, &macSFReply, putDlgID, NULL);
  1709.     HUnlock((Handle) prompt);
  1710.     if (macSFReply.good) {
  1711.         aFile = new CDataFile;
  1712.         aFile->IDataFile();
  1713.         aFile->SFSpecify(&macSFReply);
  1714.         aFile->GetFSSpec(&fileSpec);
  1715.         StdAppVol = fileSpec.vRefNum;
  1716.         StdAppDir = fileSpec.parID;
  1717.         CopyPString(fileSpec.name,StdAppName);
  1718.         return TRUE;
  1719.     } 
  1720.     else return FALSE;
  1721. }
  1722.  
  1723.  
  1724. ProcessSerialNumber CHarvestDoc::RunApp(void)
  1725. {
  1726.     FSSpec theApp;
  1727.     CFile *theFile;
  1728.     ProcessSerialNumber defaultResult = {0};
  1729.     FSMakeFSSpec(StdAppVol,
  1730.                 StdAppDir,
  1731.                 StdAppName,
  1732.                 &theApp);
  1733.     theFile = new CFile;
  1734.     theFile->IFile();
  1735.     theFile->SpecifyFSSpec(&theApp);
  1736.     if (theFile->ExistsOnDisk()) {
  1737.         LaunchParamBlockRec myLaunchParams;
  1738.         OSErr launchErr;
  1739.         ForgetObject(theFile);
  1740.         myLaunchParams.launchBlockID = extendedBlock;
  1741.         myLaunchParams.launchEPBLength = extendedBlockLen;
  1742.         myLaunchParams.launchFileFlags = 0;
  1743.         myLaunchParams.launchControlFlags = launchContinue + launchNoFileFlags;
  1744.         myLaunchParams.launchAppSpec = &theApp;
  1745.         myLaunchParams.launchAppParameters = NULL;
  1746.         launchErr = LaunchApplication(&myLaunchParams);
  1747.         FailOSErr(launchErr);
  1748.         return myLaunchParams.launchProcessSN;
  1749.     }
  1750.     else {
  1751.         SysBeep(1);
  1752.     }
  1753.     ForgetObject(theFile);
  1754.     return defaultResult;
  1755. }
  1756.  
  1757. void CHarvestDoc::Clean(void) {
  1758.     int CountSourceFiles;
  1759.     int i;
  1760.     CSourceFile *aFile;
  1761.     CDataFile *objFile;
  1762.  
  1763.     CountSourceFiles = itsSourceFiles->GetNumItems();
  1764.     for (i=1;i<=CountSourceFiles;i++) {
  1765.         aFile = (CSourceFile *) itsSourceFiles->NthItem(i);
  1766.         if (aFile->itsKind == H_SourceFile) {
  1767.             objFile = aFile->GetObjectFile();
  1768.             if (objFile->ExistsOnDisk())
  1769.                 objFile->ThrowOut();
  1770.         }
  1771.     }
  1772. }
  1773.  
  1774. Boolean CHarvestDoc::Link(void) {
  1775.     if (PickAppName()) {
  1776.         if (BringUpToDate()) {
  1777.             return DoLink();
  1778.         }
  1779.         return FALSE;
  1780.     }
  1781.     return FALSE;
  1782. }
  1783.  
  1784. Boolean CHarvestDoc::CheckLink(void) {
  1785.     SysBeep(1);
  1786. }
  1787.  
  1788. Boolean EqualPStrings(unsigned char *a,unsigned char *b) {
  1789.     int i,len;
  1790.     if (*a == *b) {
  1791.         len = *a;
  1792.         i = 1;
  1793.         while (a[i] == b[i]) {
  1794.             i++;
  1795.             if (i>len) return TRUE;
  1796.         }
  1797.     }
  1798.     return FALSE;
  1799. }
  1800.  
  1801. int CHarvestDoc::FindFile(char *name,short vRefNum,long dirID)
  1802. {
  1803.     /* Locate the given file, return its index in the list */
  1804.     int CountSourceFiles;
  1805.     int i;
  1806.     CSourceFile *aFile;
  1807.     CDataFile *theFile;
  1808.  
  1809.     CountSourceFiles = itsSourceFiles->GetNumItems();
  1810.     for (i=1;i<=CountSourceFiles;i++) {
  1811.         aFile = (CSourceFile *) itsSourceFiles->NthItem(i);
  1812.         theFile = aFile->theFile;
  1813.         if (theFile->volNum == vRefNum) {
  1814.             if (theFile->dirID == dirID) {
  1815.                 if (EqualPStrings((unsigned char *) name,theFile->name)) {
  1816.                     return i;
  1817.                 }
  1818.             }
  1819.         }
  1820.     }
  1821.     return 0;
  1822. }
  1823.  
  1824. void CHarvestDoc::ResetGopher(void)
  1825. {
  1826.     gGopher = itsGopher = itsMainPane;
  1827. }
  1828.  
  1829. void CHarvestDoc::Activate(void)
  1830. {
  1831.     ResetGopher();
  1832.     inherited::Activate();
  1833. }
  1834.